package com.jianyitech.asr.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jianyitech.asr.mapper.TenantMapper;
import com.jianyitech.asr.dtos.Tenant;
import com.jianyitech.asr.dtos.TenantIp;
import com.jianyitech.asr.dtos.TenantProduct;
import com.jianyitech.asr.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Service
public class TenantService {


    private static final Logger logger = LoggerFactory.getLogger(TenantService.class);

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    TenantMapper tenantMapper;

    public TenantIp fetchTenantByIp(String ip){
        TenantIp result = new TenantIp();
        result.setIp(ip);
        boolean exists = redisTemplate.hasKey(DIC_FILTER_TENANT_ALL_IP);
        if(exists){
            result.setTenantId(StringUtil.trim(redisTemplate.opsForHash().get(DIC_FILTER_TENANT_ALL_IP,ip)));

        }else{
            List<TenantIp> tenantList = tenantMapper.queryAllTenantIp();
            if(null!=tenantList && !tenantList.isEmpty()){
                Map<String,String> tenantIdMap = new HashMap<>();
                Map<String,String> agentIdMap = new HashMap<>();
                tenantList.stream().forEach(e -> {
                    tenantIdMap.put(e.getIp(),e.getTenantId());

                });
                redisTemplate.opsForHash().putAll(DIC_FILTER_TENANT_ALL_IP,tenantIdMap);
                redisTemplate.opsForHash().putAll(DIC_FILTER_TENANT_AGENTID,agentIdMap);
                redisTemplate.expire(DIC_FILTER_TENANT_ALL_IP,1, TimeUnit.HOURS);
                redisTemplate.expire(DIC_FILTER_TENANT_AGENTID,1,TimeUnit.HOURS);
                result.setTenantId(tenantIdMap.get(ip));

            }
        }

        return result;
    }

    /**
     * 租户账户的余额是否充足
     * @param tenantId
     * @return
     */
    public boolean hasBalance(String tenantId){
        boolean result = false;
        String accountKey = "ACC:" + tenantId;
        Map<Object, Object> map = redisTemplate.opsForHash().entries(accountKey);
        String balance = "0";
        String overdraft = "0";
        if(null!=map &&  !map.isEmpty()) {
            balance = map.containsKey("balance") ? StringUtil.trim(map.get("balance")) : "0";
            overdraft = map.containsKey("overdraft") ? StringUtil.trim(map.get("overdraft")) : "0";
        }else{
            Tenant tenant = tenantMapper.findById(tenantId);
            if(null!=tenant){
                Map<String,String> elements = new HashMap<>();
                balance = tenant.getBalance()+"";
                overdraft = tenant.getOverdraft()+"";
                elements.put("balance",balance);
                elements.put("overdraft",overdraft);
                redisTemplate.opsForHash().putAll(accountKey,elements);
                redisTemplate.expire(accountKey,5,TimeUnit.MINUTES);
            }
        }
        long total = Long.parseLong(balance) + Long.parseLong(overdraft);
        if (total > 0) { //余额充足
            result = true;
        }
        return result;
    }

    /**
     * 代理商账户的余额是否充足
      * @param agentId
     * @return
     */
    public boolean agentHasBalance(String agentId){
        boolean result = false;
        String accountKey = "AGENT:" + agentId;
        Map<Object, Object> map = redisTemplate.opsForHash().entries(accountKey);
        String balance = map.containsKey("balance") ? StringUtil.trim(map.get("balance")) : "0";
        String overdraft = map.containsKey("overdraft") ? StringUtil.trim(map.get("overdraft")) : "0";
        long total = Long.parseLong(balance) + Long.parseLong(overdraft);
        if (total > 0) { //余额充足
            result = true;
        }
        return result;
    }


    private static final String DIC_FILTER_TENANT_ALL_IP="FILTER:TENANTS:FULL";

    private static final String DIC_FILTER_TENANT_AGENTID="FILTER:TENANTS:AGENT";

    private static final String DIC_ASR_TENANT_PRODUCT_NAME="ASR:TENANTS:PRODUCT:1003";


    private static final String DIC_ASR_TENANT_STAT="ASR:TENANT:CLIENT:STAT:";


    private static final String DIC_ASR_TENANT_EXTERNALID="ASR:TENANT:EXTERNALID";


    /**
     * 获取所有的租户对应的语音质检产品设置信息
     * @return
     */
    public List<TenantProduct> fetchAsrProduct(){
        Map<String,Object> params = new HashMap<>();
        params.put("productType","1003");
        List<TenantProduct> productList =  tenantMapper.queryProductByParams(params);
        return productList;
    }

    /**
     * 获取语音质检的产品设置信息
     */
    public String  fetchAsrProductSetting(String tenantId){
        String result = null;
        boolean exists = redisTemplate.hasKey(DIC_ASR_TENANT_PRODUCT_NAME);
        if(!exists){
            List<TenantProduct> tenantList = this.fetchAsrProduct();
            if(null!=tenantList && !tenantList.isEmpty()){
                Map<String,String> elements = new HashMap<>();
                tenantList.stream().forEach(e -> {
                    elements.put(e.getTenantId(), JSON.toJSONString(e));
                });
                redisTemplate.opsForHash().putAll(DIC_ASR_TENANT_PRODUCT_NAME,elements);
                redisTemplate.expire(DIC_ASR_TENANT_PRODUCT_NAME,1,TimeUnit.HOURS);
                result = elements.get(tenantId);
            }
        }else{
            result =StringUtil.trim(redisTemplate.opsForHash().get(DIC_ASR_TENANT_PRODUCT_NAME,tenantId));
        }

        return result;
    }

    /**
     * 是否对该录音进行质检
     * @return
     */
    public boolean allowDetection(String tenantId,String name){
        boolean result = false;
        String[] arr = name.split("-");
        String caller = arr[1];
        String callee = arr[2];
        if(StringUtil.isPresent(caller)){
            String[] _arr = caller.split("_");
            caller = _arr[0];
        }
        if(StringUtil.isPresent(callee)){
            String[] _arr = callee.split("_");
            callee = _arr[0];
        }
         String json = this.fetchAsrProductSetting(tenantId);
        if(StringUtil.isPresent(json)){
           result = true;
           TenantProduct product = JSONObject.parseObject(json,TenantProduct.class);
           if(null!=product){
               String allowPrefix = product.getAllowPrefix();
               String allowCaller = product.getAllowCaller();
               Integer asrPercent = product.getAsrPercent();
               if(StringUtil.isPresent(allowPrefix) && allowPrefix.equals("1")){ //指定前缀呼叫
                   result  = matchPrefix(product,callee);
               }
               if(result && StringUtil.isPresent(allowCaller) && allowCaller.equals("1")){ //指定主叫质检
                   result = matchCaller(product,caller);
               }
               if(result && null!= asrPercent && asrPercent!=100){ //当前的质检比例是否超过设置的阀值
                    boolean flag = overPercent(tenantId,asrPercent);
                    if(!flag) {
                        // int random = random(1, 100);
                        //result = random<=asrPercent;
                        result = true;
                    }else{
                        result = false;
                        logger.error("tenantId -> {},caller -> {}, asrPercent -> {}, message -> {}",tenantId,caller,asrPercent,"质检比例已超过设定比例");
                    }
               }
           }
           if(result){
               redisTemplate.opsForHash().increment(DIC_ASR_TENANT_STAT+tenantId,"hit",1);
           }
        }else{
            logger.error("tenantId -> {},name -> {}, message -> {}",tenantId,name,"语音质检服务暂未开通");
        }
        return result;
    }


    public boolean matchPrefix(TenantProduct product,String caller){
       boolean flag = false;
       String prefix = StringUtil.trim(product.getPrefix());
       String[] prefixArr = prefix.split(",");
       List<String> prefixList = Arrays.asList(prefixArr);
       for(String str  : prefixList){
           if(StringUtil.isPresent(str) && caller.startsWith(str)){
               flag = true;
               break;
           }
       }
        if(!flag){
            logger.info("tenantId-> {} , prefix -> {}, caller -> {}, message -> {} ",product.getTenantId(),prefix,caller,"质检号码前缀不匹配");
        }
       return flag;
    }


    public boolean matchCaller(TenantProduct product,String caller){
        boolean flag  = false;
        String callerStr = StringUtil.trim(product.getCaller());
        String[] callerArr = callerStr.split(",");
        List<String> callerList = Arrays.asList(callerArr);
        flag = callerList.contains(caller);
        if(!flag){
            logger.info("tenantId-> {} , callers -> {}, caller -> {}, message -> {} ",product.getTenantId(),callerStr,caller,"质检号码不匹配");
        }
        return flag;
    }


    public boolean overPercent(String tenantId,int asrPercent){
        boolean result = false;
        String key = DIC_ASR_TENANT_STAT+tenantId;
        Map<Object,Object> map = redisTemplate.opsForHash().entries(key);
        String hitStr = map.containsKey("hit")?StringUtil.trim(map.get("hit")):"0";
        String totalStr = map.containsKey("total")?StringUtil.trim(map.get("total")):"0";
        long  hit = Long.parseLong(hitStr);
        long total = Long.parseLong(totalStr);
        if(hit>0 && total>0){
            int percent = new BigDecimal(hit).divide(new BigDecimal(total),2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
            result = percent>=asrPercent;
        }
        if(result){
            logger.info("tenantId-> {} , asrPercent -> {}, hit -> {}, total -> {}, message -> {} ",tenantId,asrPercent,hit,total,"超过抽检比例");
        }
        return result;
    }


    private int random(int min,int max){
        Random random = new Random();
        return  random.nextInt(max)%(max-min+1)+min;
    }


    public int getMaxLen(String tenantId){
        int result = 180;
        try {
            String json = this.fetchAsrProductSetting(tenantId);
            if (StringUtil.isPresent(json)) {
                TenantProduct tenantProduct = JSONObject.parseObject(json,TenantProduct.class);
                if(null!=tenantProduct){
                    Integer len =tenantProduct.getMaxLen();
                    if(null!=len && len>0){
                        result = len;
                    }
                }

            }
        }catch(Exception e){
            //doNothing
        }finally {
            return result;
        }
    }


    public Tenant findById(String id){
        return tenantMapper.findById(id);
    }



    /**
     * 获取租户对应的外部系统id
     */
    public String  fetchTenantIdByExternalId(String externalId){
        String result = null;
        boolean exists = redisTemplate.hasKey(DIC_ASR_TENANT_EXTERNALID);
        if(!exists){
            List<Tenant> tenantList = tenantMapper.queryAllTenantExternalId();
            if(null!=tenantList && !tenantList.isEmpty()){
                Map<String,String> elements = new HashMap<>();

                redisTemplate.opsForHash().putAll(DIC_ASR_TENANT_EXTERNALID,elements);
                redisTemplate.expire(DIC_ASR_TENANT_EXTERNALID,1,TimeUnit.HOURS);
                result = elements.get(externalId);
            }
        }else{
            result =StringUtil.trim(redisTemplate.opsForHash().get(DIC_ASR_TENANT_EXTERNALID,externalId));
        }

        return result;
    }



}
